views_embed_view is just a wrapper for views_get_view:

    function views_embed_view($name, $display_id = 'default') {
      $args = func_get_args();
      array_shift($args); // remove $name
      if (count($args)) {
        array_shift($args); // remove $display_id
      }
    
      $view = views_get_view($name);
      if (!$view || !$view->access($display_id)) {
        return;
      }
    
      return $view->preview($display_id, $args);
    }

So how would you set dynamic arguments on views_embed_view? With views_get_view you can at least do this:

      $view = views_get_view($view_name);
      if (!$view || !$view->access($display_id)) {
        return;
      }
      $view->set_display($display_id);
      $view->set_arguments($variables);
      $view->pre_execute();
      $view->execute();
      return $view->render();

module_invoke for block is too roundabout and limited for my liking. Why limit yourself to a block when you can choose from any display available?

views_block_view contains this snippet:

    if ($view = views_get_view($name)) {

So it also uses Views_get_view.

Performance-wise I reckon the differences are negligible.

So, IMO, views_get_view wins.