For the second snippet,
auto f() {
  std::vector<int> v0(100000);
  std::vector<int> v1(100000);
  return std::make_pair(std::move(v0),std::move(v1)); // is the move needed?
}
return returns the result of the std::make_pair() function. That's an RValue.
However, the OP's question probably condenses to whether (or why not) Named Return Value Optimization still applies to v0/v1 when returned as a std::pair.
Thereby, it's overlooked that v0/v1 aren't subject of return anymore, but become arguments of std::make_pair(). As such, v0/v1 are LValues – std::move(v0), std::move(v1) have to be applied to turn them into RValues if move-semantic is intended.
Demo on coliru:
#include <iostream>
template <typename T>
struct Vector {
  Vector(size_t n)
  {
    std::cout << "Vector::Vector(" << n << ")\n";
  }
  Vector(const Vector&)
  {
    std::cout << "Vector::Vector(const Vector&)\n";
  }
  Vector(const Vector&&)
  {
    std::cout << "Vector::Vector(const Vector&&)\n";
  }
  
};
auto f1() {
  Vector<int> v(100000);
  return std::move(v); // over-pessimistic
}
auto f2() {
  Vector<int> v(100000);
  return v; // allows NRVO
}
auto f3() {
  Vector<int> v0(100000);
  Vector<int> v1(100000);
  return std::make_pair(v0, v1); // copy constructor called for v0, v1
}    
auto f4() {
  Vector<int> v0(100000);
  Vector<int> v1(100000);
  return std::make_pair(std::move(v0),std::move(v1)); // move constructor called for v0, v1
}
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ 
int main()
{
  DEBUG(f1());
  DEBUG(f2());
  DEBUG(f3());
  DEBUG(f4());
}
Output:
f1();
Vector::Vector(100000)
Vector::Vector(const Vector&&)
f2();
Vector::Vector(100000)
f3();
Vector::Vector(100000)
Vector::Vector(100000)
Vector::Vector(const Vector&)
Vector::Vector(const Vector&)
f4();
Vector::Vector(100000)
Vector::Vector(100000)
Vector::Vector(const Vector&&)
Vector::Vector(const Vector&&)