Thanks! Can you point me to a source of documentation beyond what I’ve linked, that describes how exactly autograd::grad works? Should I go into the source code?
Here’s one more even simpler example
        std::vector<double> e {1, 0, 0}; 
        auto x = torch::from_blob(e.data(),3,torch::requires_grad());
        auto f = dot(x,x); 
        std::cout << "x = \n" << x << std::endl;
        std::cout << "f = dot(x,x) = " << f << std::endl;

        auto partial_f_x = torch::autograd::grad({f}, {x});
        std::cout << "partial_f_x = \n" << partial_f_x << std::endl; 


with the output:
[ CPUDoubleType{1} ]
x = 
 1
 0
 0
[ CPUDoubleType{3} ]
f = dot(x,x) = 1
[ CPUDoubleType{} ]
partial_f_x = 
 2
 0
 0
[ CPUDoubleType{3} ]


so if x in R^3, partial_x (dot(x,x))=2x.