def _apply_perturbation(
        self, x: "tf.Tensor", perturbation: "tf.Tensor", eps_step: int | float | np.ndarray
    ) -> "tf.Tensor":
        """
        Apply perturbation on examples.

        :param x: Current adversarial examples.
        :param perturbation: Current perturbations.
        :param eps_step: Attack step size (input variation) at each iteration.
        :return: Adversarial examples.
        """
        import tensorflow as tf

        perturbation_step = tf.constant(eps_step, dtype=ART_NUMPY_DTYPE) * perturbation
        perturbation_step = tf.where(tf.math.is_nan(perturbation_step), 0, perturbation_step)
        x = x + perturbation_step
        if self.estimator.clip_values is not None:
            clip_min, clip_max = self.estimator.clip_values
            x = tf.clip_by_value(x, clip_value_min=clip_min, clip_value_max=clip_max)

        return x

        Apply perturbation on examples.

        :param x: Current adversarial examples.
        :param perturbation: Current perturbations.
        :param eps_step: Attack step size (input variation) at each iteration.
        :return: Adversarial examples.
        
art/attacks/evasion/projected_gradient_descent/projected_gradient_descent_tensorflow_v2.py