Makes a step in all environments.

    Does any preprocessing and records frames.

    Args:
      actions: Batch of actions.

    Returns:
      (obs, rewards, dones) - batches of observations, rewards and done flags
      respectively.

    Raises:
      ValueError: when the data for current epoch has already been loaded.

def step(self, actions):
    """Makes a step in all environments.

    Does any preprocessing and records frames.

    Args:
      actions: Batch of actions.

    Returns:
      (obs, rewards, dones) - batches of observations, rewards and done flags
      respectively.

    Raises:
      ValueError: when the data for current epoch has already been loaded.
    """
    if self._store_rollouts and \
        self._rollouts_by_epoch_and_split[self.current_epoch]:
      raise ValueError(
          "Data for current epoch has already been loaded from disk."
      )
    (obs, unclipped_rewards, dones) = self._step(actions)
    obs = self._preprocess_observations(obs)
    (min_reward, max_reward) = self.reward_range
    rewards = np.around(np.clip(unclipped_rewards, min_reward, max_reward))
    if self._store_rollouts:
      unclipped_rewards = unclipped_rewards.astype(np.float64)
      encoded_obs = self._encode_observations(obs)
      for (rollout, frame, action) in zip(
          self._current_batch_rollouts, self._current_batch_frames, actions
      ):
        rollout.append(frame._replace(action=action))

      # orud = (observation, reward, unclipped_reward, done)
      self._current_batch_frames = [
          Frame(*orud, action=None)
          for orud in zip(encoded_obs, rewards, unclipped_rewards, dones)
      ]
    return (obs, rewards, dones)