class_docstr: A graph total variation convolutional layer (GTVConv) from the paper
  
  > [Total Variation Graph Neural Networks](https://arxiv.org/abs/2211.06218)<br>
  > Jonas Berg Hansen and Filippo Maria Bianchi
  
  **Mode**: single, disjoint, batch.
  
  This layer computes
  $$
      \X' = \sigma\left[\left(\I - \delta\L_\hat{\mathbf{\Gamma}}\right) \tilde{\X} \right]
  $$
  where
  $$
      \begin{align}
          \tilde{\X} &= \X \W\\[5pt]
          \L_\hat{\mathbf{\Gamma}} &= \D_\mathbf{\hat{\Gamma}} - \hat{\mathbf{\Gamma}}\\[5pt]
          [\hat{\mathbf{\Gamma}}]_{ij} &= \frac{[\mathbf{A}]_{ij}}{\max\{||\tilde{\x}_i-\tilde{\x}_j||_1, \epsilon\}}\\
      \end{align}
  $$
  
  **Input**
  
  - Node features of shape `(batch, n_nodes, n_node_features)`;
  - Adjacency matrix of shape `(batch, n_nodes, n_nodes)`;
  
  **Output**
  
  - Node features with the same shape as the input, but with the last
  dimension changed to `channels`.
  
  **Arguments**
  
  - `channels`: number of output channels;
  - `delta_coeff`: step size for gradient descent of GTV
  - `epsilon`: small number used to numerically stabilize the computation of new adjacency weights
  - `activation`: activation function;
  - `use_bias`: bool, add a bias vector to the output;
  - `kernel_initializer`: initializer for the weights;
  - `bias_initializer`: initializer for the bias vector;
  - `kernel_regularizer`: regularization applied to the weights;
  - `bias_regularizer`: regularization applied to the bias vector;
  - `activity_regularizer`: regularization applied to the output;
  - `kernel_constraint`: constraint applied to the weights;
  - `bias_constraint`: constraint applied to the bias vector.
code: def build(self, input_shape):
      assert len(input_shape) >= 2
      input_dim = input_shape[0][-1]
      self.kernel = self.add_weight(
          shape=(input_dim, self.channels),
          initializer=self.kernel_initializer,
          name="kernel",
          regularizer=self.kernel_regularizer,
          constraint=self.kernel_constraint,
      )
      if self.use_bias:
          self.bias = self.add_weight(
              shape=(self.channels,),
              initializer=self.bias_initializer,
              name="bias",
              regularizer=self.bias_regularizer,
              constraint=self.bias_constraint,
          )
      self.built = True
  
file_path: spektral/spektral/layers/convolutional/gtv_conv.py
imports: import tensorflow
  from tensorflow.keras import backend
  from spektral.layers import ops
  from spektral.layers.convolutional.conv import Conv
label_desc: Use image node_id 2 for calling the GTVConv obj's underlying member method code with example usage: obj.build(input_shape) without return types