class_docstr: Triangular distribution with `low`, `high` and `peak` parameters.
  
  #### Mathematical Details
  
  The Triangular distribution is specified by two line segments in the plane,
  such that:
  
    * The first line segment starts at `(a, 0)` and ends at `(c, z)`.
    * The second line segment starts at `(c, z)` and ends at `(b, 0)`.
  
    ```none
    y
  
    ^
  z |           o  (c,z)
    |          / \
    |         /   \
    |        /     \
    | (a,0) /       \ (b,0)
  0 +------o---------o-------> x
    0      a    c    b
  ```
  
  where:
  * a <= c <= b, a < b
  * `low = a`,
  * `high = b`,
  * `peak = c`,
  * `z = 2 / (b - a)`
  
  The parameters `low`, `high` and `peak` must be shaped in a way that supports
  broadcasting (e.g., `high - low` is a valid operation).
  
  #### Examples
  
  ```python
  import tensorflow_probability as tfp
  tfd = tfp.distributions
  
  # Specify a single Triangular distribution.
  u1 = tfd.Triangular(low=3., high=4., peak=3.5)
  u1.mean()
  # ==> 3.5
  
  # Specify two different Triangular distributions.
  u2 = tfd.Triangular(low=[1., 2.], high=[3., 4.], peak=[2., 3.])
  u2.mean()
  # ==> [2., 3.]
  
  # Specify three different Triangular distributions by leveraging broadcasting.
  u3 = tfd.Triangular(low=3., high=[5., 6., 7.], peak=3.)
  u3.mean()
  # ==> [3.6666, 4., 4.3333]
  ```
code: def _sample_n(self, n, seed=None):
      low = tf.convert_to_tensor(self.low)
      high = tf.convert_to_tensor(self.high)
      peak = tf.convert_to_tensor(self.peak)
  
      seed = samplers.sanitize_seed(seed, salt="triangular")
      shape = ps.concat(
          [
              [n],
              self._batch_shape_tensor(low=low, high=high, peak=peak),
          ],
          axis=0,
      )
      samples = samplers.uniform(
          shape=shape, dtype=self.dtype, seed=seed
      )
      # We use Inverse CDF sampling here. Because the CDF is a quadratic function,
      # we must use sqrts here.
      interval_length = high - low
      return tf.where(
          # Note the CDF on the left side of the peak is
          # (x - low) ** 2 / ((high - low) * (peak - low)).
          # If we plug in peak for x, we get that the CDF at the peak
          # is (peak - low) / (high - low). Because of this we decide
          # which part of the piecewise CDF we should use based on the cdf samples
          # we drew.
          samples < (peak - low) / interval_length,
          # Inverse of (x - low) ** 2 / ((high - low) * (peak - low)).
          low + tf.sqrt(samples * interval_length * (peak - low)),
          # Inverse of 1 - (high - x) ** 2 / ((high - low) * (high - peak))
          high
          - tf.sqrt((1.0 - samples) * interval_length * (high - peak)),
      )
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import sigmoid
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.internal import tensor_util
label_desc: Use image node_id 8 for calling the Triangular obj's underlying member method code with example usage: obj._sample_n(n, seed) and returns: tf