Yes, Function’s __call__ will prepare the object, call the forward method (implemented by the user), and do some postprocessing of the results (e.g. wrap them in Variables). These two steps is when the graph is built, and the function object is saved in there, so it can be found during backward and asked to compute the derivative.
*repeat(...) is just Python syntax, nothing specific to PyTorch. Look for the docs in itertools package. expand_as is necessary to make sure that the multiplied tensors are of the same length. It will fake that the object on which it was called it in fact a bigger tensor with some tricks (no memory copy needed). Note that you can only expand along new dimensions at the front (pretend that the tensor has more dimensions than it really has), or along dims of size 1.