Background
As you already know, wp_nav_menu() function takes an array $args as argument & menu is one of the keys to that $args array.
The key menu for the argument $args is defined as:
(int|string|WP_Term) Desired menu. Accepts (matching in order) id, slug, name, menu object.
Now, if you look deep into the implementation of wp_nav_menu() function, you’ll see that, no matter what value you provide, whether it is an int id, a string name, a string slug or an object WP_Term, it’ll always retrieve the WP_Term object for the corresponding menu id | name | slug before creating the menu.
For example: if you have a menu with id 3, name My Menu and slug my-menu; you can add that menu using any of the following CODE:
// with id: 3
wp_nav_menu( array(
'menu' => 3
) );
// with name: My Menu
wp_nav_menu( array(
'menu' => "My Menu"
) );
// with slug: my-menu
wp_nav_menu( array(
'menu' => "my-menu"
) );
Even if you don’t provide the menu argument, it’ll try to get the WP_Term object from other arguments like theme_location.
For example: say the menu location top was registered using register_nav_menus() function in your theme’s functions.php file & the menu named My Menu was asigned to the top location from your WP admin panel. In that case, you can get the same menu using:
wp_nav_menu( array(
'theme_location' => 'top'
) );
In each of the above cases, wp_nav_menu() function retrieves the WP_Term object before generating the menu. It uses the wp_get_nav_menu_object() function to do so.
Implementation
So instead of theme_location argument, or menu argument as int id or string name | slug, you can directly provide the corresponding WP_Term object.
One way get the WP_Term object is by using the WP_Term::get_instance() method:
// get the WP_Term object using menu id 3
$menu_obj = WP_Term::get_instance( 3, 'nav_menu' );
You can also get the WP_Term object with menu name | slug using get_term_by() function:
// by menu slug
$menu_obj = get_term_by( 'slug', 'my-menu', 'nav_menu' );
// or, by menu name
$menu_obj = get_term_by( 'name', 'My Menu', 'nav_menu' );
Now that you’ve got the WP_Term object $menu_obj, you can use that to generate the menu:
wp_nav_menu( array(
'menu' => $menu_obj
) );
Use case:
So you know how to generate a menu using WP_Term object as an argument to wp_nav_menu() function. Now the question is: why will you want to use it? Apart from the fact that it’s just another option, you may want to use it because it may be a slightly faster option.
For example, if you want to use the same menu twice, once in the header & then in the footer, in that case, instead of using menu id | slug | name, you may create WP_Term object in your template for header menu:
global $menu_obj;
$menu_obj = WP_Term::get_instance( 3, 'nav_menu' );
wp_nav_menu( array(
'menu' => $menu_obj,
'menu_id' => 'header_menu'
) );
and then simply use $menu_obj in the footer template as well:
// global declaration is needed to access the global variable from another template
global $menu_obj;
wp_nav_menu( array(
'menu' => $menu_obj,
'menu_id' => 'footer_menu'
) );
If you look into the implementation of wp_nav_menu() function, you’ll see that by doing it this way, you will avoid a few extra function calls in WordPress core, thus the total execution will be slightly faster.
However, please remember that using theme_location argument or other options may be more convenient & better for maintenance. So whether or not you should use it totally depends on your own particular scenario. I just explained that you can & how, nothing more.