class_docstr: An exploration that adds white noise to continuous actions.
  
  If explore=True, returns actions plus scale (annealed over time) x
  Gaussian noise. Also, some completely random period is possible at the
  beginning.
  
  If explore=False, returns the deterministic action.
class_docstr_tok: ["An","exploration","that","adds","white","noise","to","continuous","actions",".","If","explore=True",",","returns","actions","plus","scale","(","annealed","over","time",")","x","Gaussian","noise",".","Also",",","some","completely","random","period","is","possible","at","the","beginning",".","If","explore=False",",","returns","the","deterministic","action","."]
code: def _get_tf_exploration_action_op(
      self,
      action_dist: ActionDistribution,
      explore: bool,
      timestep: Union[int, TensorType],
  ):
      ts = timestep if timestep is not None else self.last_timestep
  
      # The deterministic actions (if explore=False).
      deterministic_actions = action_dist.deterministic_sample()
  
      # Take a Gaussian sample with our stddev (mean=0.0) and scale it.
      gaussian_sample = self.scale_schedule(ts) * tf.random.normal(
          tf.shape(deterministic_actions), stddev=self.stddev
      )
  
      # Stochastic actions could either be: random OR action + noise.
      (
          random_actions,
          _,
      ) = self.random_exploration.get_tf_exploration_action_op(
          action_dist, explore
      )
      stochastic_actions = tf.cond(
          pred=tf.convert_to_tensor(ts < self.random_timesteps),
          true_fn=lambda: random_actions,
          false_fn=lambda: tf.clip_by_value(
              deterministic_actions + gaussian_sample,
              self.action_space.low
              * tf.ones_like(deterministic_actions),
              self.action_space.high
              * tf.ones_like(deterministic_actions),
          ),
      )
  
      # Chose by `explore` (main exploration switch).
      action = tf.cond(
          pred=tf.constant(explore, dtype=tf.bool)
          if isinstance(explore, bool)
          else explore,
          true_fn=lambda: stochastic_actions,
          false_fn=lambda: deterministic_actions,
      )
      # Logp=always zero.
      logp = zero_logps_from_actions(deterministic_actions)
  
      # Increment `last_timestep` by 1 (or set to `timestep`).
      if self.framework == "tf2":
          if timestep is None:
              self.last_timestep.assign_add(1)
          else:
              self.last_timestep.assign(tf.cast(timestep, tf.int64))
          return action, logp
      else:
          assign_op = (
              tf1.assign_add(self.last_timestep, 1)
              if timestep is None
              else tf1.assign(self.last_timestep, timestep)
          )
          with tf1.control_dependencies([assign_op]):
              return action, logp
  
imports: from gymnasium.spaces import Space
  import numpy
  from typing import Union, Optional
  from ray.rllib.models.action_dist import ActionDistribution
  from ray.rllib.models.modelv2 import ModelV2
  from ray.rllib.utils.annotations import override, PublicAPI
  from ray.rllib.utils.exploration.exploration import Exploration
  from ray.rllib.utils.exploration.random import Random
  from ray.rllib.utils.framework import try_import_tf, try_import_torch, get_variable, TensorType
  from ray.rllib.utils.numpy import convert_to_numpy
  from ray.rllib.utils.schedules import Schedule
  from ray.rllib.utils.schedules.piecewise_schedule import PiecewiseSchedule
  from ray.rllib.utils.tf_utils import zero_logps_from_actions
label_desc: Use image node_id 3 for calling the GaussianNoise obj's underlying member method code with example usage: obj._get_tf_exploration_action_op(action_dist, explore, timestep) and returns: action,  logp, action,  logp