For each trainable parameter, the gradient is accumulated/added up in its .grad buffer (for example, conv.weight.grad, conv.bias.grad) and later used by the optimizer (such as Adam, SGD) for gradient descent.