docs: def get_step(self, grad):
          """Computes the 'step' to take for the next gradient descent update.
  
          Returns the step rather than performing the update so that
          parameters can be updated in place rather than overwritten.
  
          Examples
          --------
          >>> gradient = # ...
          >>> optimizer = AdaGradOptimizer(0.01)
          >>> params -= optimizer.get_step(gradient)
  
          Parameters
          ----------
          grad
  
          Returns
          -------
          np.array
              Size matches `grad`.
          """
          if self._momentum is None:
              self._momentum = self.initial_accumulator_value * np.ones_like(grad)
          self._momentum += grad ** 2
          return self.learning_rate * grad / np.sqrt(self._momentum)