I always did wonder why in the source code of the optimizers, they loop over the given parameters and skip a parameter if its grad is None. For example, from the SGD source 2…
def step(self, closure=None):
    ...
    for group in self.param_groups:
        ...
        for p in group['params']:
            if p.grad is None:
                continue
            ...