class_docstr: Randomly generates observations following the given observation_spec.
  
  If an action_spec is provided it validates that the actions used to step the
  environment fall within the defined spec.
code: def _step(self, action):
      if self._action_spec:
          nest_utils.assert_same_structure(self._action_spec, action)
  
      self._num_steps += 1
  
      observation = self._get_observation()
      if self._num_steps < self._min_duration:
          self._done = False
      elif self._max_duration and self._num_steps >= self._max_duration:
          self._done = True
      else:
          self._done = (
              self._rng.uniform() < self._episode_end_probability
          )
  
      if self._done:
          reward = self._reward_fn(
              ts.StepType.LAST, action, observation
          )
          self._check_reward_shape(reward)
          time_step = ts.termination(observation, reward)
          self._num_steps = 0
      else:
          reward = self._reward_fn(ts.StepType.MID, action, observation)
          self._check_reward_shape(reward)
          time_step = ts.transition(observation, reward, self._discount)
  
      return time_step
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from typing import Callable, Optional, Sequence, Text
  import numpy
  from tf_agents.environments import py_environment
  from tf_agents.specs import array_spec
  from tf_agents.trajectories import time_step
  from tf_agents.typing import types
  from tf_agents.utils import nest_utils
label_desc: Use image node_id 9 for calling the RandomPyEnvironment obj's underlying member method code with example usage: obj._step(action) and returns: time_step