We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Significant LazyAdam optimizer performance degradation since PR#1988
**System information**
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): Reproducible on Colab
- TensorFlow version and how it was installed (source or binary): TF 2.3.0
- TensorFlow-Addons version and how it was installed (source or binary): TF 0.11.2
- Python version: 3.6.9
- Is GPU used? (yes/no): no (but issue observed on GPU as well)

**Describe the bug**

PR [#1988](https://github.com/tensorflow/addons/pull/1988/files) replaces calls to resource scatter update/sub/add from `tf.raw_ops` with calls to similar methods from ancestor class [OptimizerV2](https://github.com/tensorflow/tensorflow/blob/v2.3.0/tensorflow/python/keras/optimizer_v2/optimizer_v2.py#L1149-L1157).
These differ in that the OptimizerV2 method calls `.value()` on the input resource and returns a `Tensor`, whereas the `raw_ops` method returns an `Operation`.

The result is a major performance penalty with both CPU and GPU runtimes (in fact when using a GPU I have observed GPU utilization to drop to near 0%).

**Code to reproduce the issue**

Issue reproduced in this Colab on a CPU runtime with both with the Keras API and the Estimator API:
https://colab.research.google.com/drive/1IxPrQiGQn9Wgn9MtMhVTh0rdLlgZkMYo?usp=sharing


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tensorflow_addons/optimizers/lazy_adam.py`
Content:
```
1 # Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 # ==============================================================================
15 """Variant of the Adam optimizer that handles sparse updates more efficiently.
16 
17 Compared with the original Adam optimizer, the one in this file can
18 provide a large improvement in model training throughput for some
19 applications. However, it provides slightly different semantics than the
20 original Adam algorithm, and may lead to different empirical results.
21 """
22 
23 import tensorflow as tf
24 from tensorflow_addons.utils.types import FloatTensorLike
25 
26 from typeguard import typechecked
27 from typing import Union, Callable
28 
29 
30 @tf.keras.utils.register_keras_serializable(package="Addons")
31 class LazyAdam(tf.keras.optimizers.Adam):
32     """Variant of the Adam optimizer that handles sparse updates more
33     efficiently.
34 
35     The original Adam algorithm maintains two moving-average accumulators for
36     each trainable variable; the accumulators are updated at every step.
37     This class provides lazier handling of gradient updates for sparse
38     variables.  It only updates moving-average accumulators for sparse variable
39     indices that appear in the current batch, rather than updating the
40     accumulators for all indices. Compared with the original Adam optimizer,
41     it can provide large improvements in model training throughput for some
42     applications. However, it provides slightly different semantics than the
43     original Adam algorithm, and may lead to different empirical results.
44 
45     Note, amsgrad is currently not supported and the argument can only be
46     False.
47     """
48 
49     @typechecked
50     def __init__(
51         self,
52         learning_rate: Union[FloatTensorLike, Callable] = 0.001,
53         beta_1: FloatTensorLike = 0.9,
54         beta_2: FloatTensorLike = 0.999,
55         epsilon: FloatTensorLike = 1e-7,
56         amsgrad: bool = False,
57         name: str = "LazyAdam",
58         **kwargs,
59     ):
60         """Constructs a new LazyAdam optimizer.
61 
62         Args:
63           learning_rate: A `Tensor` or a floating point value. or a schedule
64             that is a `tf.keras.optimizers.schedules.LearningRateSchedule`
65             The learning rate.
66           beta_1: A `float` value or a constant `float` tensor.
67             The exponential decay rate for the 1st moment estimates.
68           beta_2: A `float` value or a constant `float` tensor.
69             The exponential decay rate for the 2nd moment estimates.
70           epsilon: A small constant for numerical stability.
71             This epsilon is "epsilon hat" in
72             [Adam: A Method for Stochastic Optimization. Kingma et al., 2014]
73             (http://arxiv.org/abs/1412.6980) (in the formula just
74             before Section 2.1), not the epsilon in Algorithm 1 of the paper.
75           amsgrad: `boolean`. Whether to apply AMSGrad variant of this
76             algorithm from the paper "On the Convergence of Adam and beyond".
77             Note that this argument is currently not supported and the
78             argument can only be `False`.
79           name: Optional name for the operations created when applying
80             gradients. Defaults to "LazyAdam".
81           **kwargs: keyword arguments. Allowed to be {`clipnorm`, `clipvalue`,
82             `lr`, `decay`}. `clipnorm` is clip gradients by norm; `clipvalue`
83             is clip gradients by value, `decay` is included for backward
84             compatibility to allow time inverse decay of learning rate. `lr`
85             is included for backward compatibility, recommended to use
86             `learning_rate` instead.
87         """
88         super().__init__(
89             learning_rate=learning_rate,
90             beta_1=beta_1,
91             beta_2=beta_2,
92             epsilon=epsilon,
93             amsgrad=amsgrad,
94             name=name,
95             **kwargs,
96         )
97 
98     def _resource_apply_sparse(self, grad, var, indices):
99         var_dtype = var.dtype.base_dtype
100         lr_t = self._decayed_lr(var_dtype)
101         beta_1_t = self._get_hyper("beta_1", var_dtype)
102         beta_2_t = self._get_hyper("beta_2", var_dtype)
103         local_step = tf.cast(self.iterations + 1, var_dtype)
104         beta_1_power = tf.math.pow(beta_1_t, local_step)
105         beta_2_power = tf.math.pow(beta_2_t, local_step)
106         epsilon_t = tf.convert_to_tensor(self.epsilon, var_dtype)
107         lr = lr_t * tf.math.sqrt(1 - beta_2_power) / (1 - beta_1_power)
108 
109         # \\(m := beta1 * m + (1 - beta1) * g_t\\)
110         m = self.get_slot(var, "m")
111         m_t_slice = beta_1_t * tf.gather(m, indices) + (1 - beta_1_t) * grad
112         m_update_op = self._resource_scatter_update(m, indices, m_t_slice)
113 
114         # \\(v := beta2 * v + (1 - beta2) * (g_t * g_t)\\)
115         v = self.get_slot(var, "v")
116         v_t_slice = beta_2_t * tf.gather(v, indices) + (1 - beta_2_t) * tf.math.square(
117             grad
118         )
119         v_update_op = self._resource_scatter_update(v, indices, v_t_slice)
120 
121         # \\(variable += -learning_rate * m_t / (epsilon_t + sqrt(v_t))\\)
122         var_slice = -lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)
123         var_update_op = self._resource_scatter_add(var, indices, var_slice)
124 
125         return tf.group(*[var_update_op, m_update_op, v_update_op])
126
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/tensorflow_addons/optimizers/lazy_adam.py b/tensorflow_addons/optimizers/lazy_adam.py
--- a/tensorflow_addons/optimizers/lazy_adam.py
+++ b/tensorflow_addons/optimizers/lazy_adam.py
@@ -119,7 +119,26 @@
         v_update_op = self._resource_scatter_update(v, indices, v_t_slice)
 
         # \\(variable += -learning_rate * m_t / (epsilon_t + sqrt(v_t))\\)
-        var_slice = -lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)
-        var_update_op = self._resource_scatter_add(var, indices, var_slice)
+        var_slice = lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)
+        var_update_op = self._resource_scatter_sub(var, indices, var_slice)
 
         return tf.group(*[var_update_op, m_update_op, v_update_op])
+
+    def _resource_scatter_update(self, resource, indices, update):
+        return self._resource_scatter_operate(
+            resource, indices, update, tf.raw_ops.ResourceScatterUpdate
+        )
+
+    def _resource_scatter_sub(self, resource, indices, update):
+        return self._resource_scatter_operate(
+            resource, indices, update, tf.raw_ops.ResourceScatterSub
+        )
+
+    def _resource_scatter_operate(self, resource, indices, update, resource_scatter_op):
+        resource_update_kwargs = {
+            "resource": resource.handle,
+            "indices": indices,
+            "updates": update,
+        }
+
+        return resource_scatter_op(**resource_update_kwargs)

{"golden_diff": "diff --git a/tensorflow_addons/optimizers/lazy_adam.py b/tensorflow_addons/optimizers/lazy_adam.py\n--- a/tensorflow_addons/optimizers/lazy_adam.py\n+++ b/tensorflow_addons/optimizers/lazy_adam.py\n@@ -119,7 +119,26 @@\n         v_update_op = self._resource_scatter_update(v, indices, v_t_slice)\n \n         # \\\\(variable += -learning_rate * m_t / (epsilon_t + sqrt(v_t))\\\\)\n-        var_slice = -lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)\n-        var_update_op = self._resource_scatter_add(var, indices, var_slice)\n+        var_slice = lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)\n+        var_update_op = self._resource_scatter_sub(var, indices, var_slice)\n \n         return tf.group(*[var_update_op, m_update_op, v_update_op])\n+\n+    def _resource_scatter_update(self, resource, indices, update):\n+        return self._resource_scatter_operate(\n+            resource, indices, update, tf.raw_ops.ResourceScatterUpdate\n+        )\n+\n+    def _resource_scatter_sub(self, resource, indices, update):\n+        return self._resource_scatter_operate(\n+            resource, indices, update, tf.raw_ops.ResourceScatterSub\n+        )\n+\n+    def _resource_scatter_operate(self, resource, indices, update, resource_scatter_op):\n+        resource_update_kwargs = {\n+            \"resource\": resource.handle,\n+            \"indices\": indices,\n+            \"updates\": update,\n+        }\n+\n+        return resource_scatter_op(**resource_update_kwargs)\n", "issue": "Significant LazyAdam optimizer performance degradation since PR#1988\n**System information**\r\n- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): Reproducible on Colab\r\n- TensorFlow version and how it was installed (source or binary): TF 2.3.0\r\n- TensorFlow-Addons version and how it was installed (source or binary): TF 0.11.2\r\n- Python version: 3.6.9\r\n- Is GPU used? (yes/no): no (but issue observed on GPU as well)\r\n\r\n**Describe the bug**\r\n\r\nPR [#1988](https://github.com/tensorflow/addons/pull/1988/files) replaces calls to resource scatter update/sub/add from `tf.raw_ops` with calls to similar methods from ancestor class [OptimizerV2](https://github.com/tensorflow/tensorflow/blob/v2.3.0/tensorflow/python/keras/optimizer_v2/optimizer_v2.py#L1149-L1157).\r\nThese differ in that the OptimizerV2 method calls `.value()` on the input resource and returns a `Tensor`, whereas the `raw_ops` method returns an `Operation`.\r\n\r\nThe result is a major performance penalty with both CPU and GPU runtimes (in fact when using a GPU I have observed GPU utilization to drop to near 0%).\r\n\r\n**Code to reproduce the issue**\r\n\r\nIssue reproduced in this Colab on a CPU runtime with both with the Keras API and the Estimator API:\r\nhttps://colab.research.google.com/drive/1IxPrQiGQn9Wgn9MtMhVTh0rdLlgZkMYo?usp=sharing\r\n\n", "before_files": [{"content": "# Copyright 2019 The TensorFlow Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ==============================================================================\n\"\"\"Variant of the Adam optimizer that handles sparse updates more efficiently.\n\nCompared with the original Adam optimizer, the one in this file can\nprovide a large improvement in model training throughput for some\napplications. However, it provides slightly different semantics than the\noriginal Adam algorithm, and may lead to different empirical results.\n\"\"\"\n\nimport tensorflow as tf\nfrom tensorflow_addons.utils.types import FloatTensorLike\n\nfrom typeguard import typechecked\nfrom typing import Union, Callable\n\n\n@tf.keras.utils.register_keras_serializable(package=\"Addons\")\nclass LazyAdam(tf.keras.optimizers.Adam):\n    \"\"\"Variant of the Adam optimizer that handles sparse updates more\n    efficiently.\n\n    The original Adam algorithm maintains two moving-average accumulators for\n    each trainable variable; the accumulators are updated at every step.\n    This class provides lazier handling of gradient updates for sparse\n    variables.  It only updates moving-average accumulators for sparse variable\n    indices that appear in the current batch, rather than updating the\n    accumulators for all indices. Compared with the original Adam optimizer,\n    it can provide large improvements in model training throughput for some\n    applications. However, it provides slightly different semantics than the\n    original Adam algorithm, and may lead to different empirical results.\n\n    Note, amsgrad is currently not supported and the argument can only be\n    False.\n    \"\"\"\n\n    @typechecked\n    def __init__(\n        self,\n        learning_rate: Union[FloatTensorLike, Callable] = 0.001,\n        beta_1: FloatTensorLike = 0.9,\n        beta_2: FloatTensorLike = 0.999,\n        epsilon: FloatTensorLike = 1e-7,\n        amsgrad: bool = False,\n        name: str = \"LazyAdam\",\n        **kwargs,\n    ):\n        \"\"\"Constructs a new LazyAdam optimizer.\n\n        Args:\n          learning_rate: A `Tensor` or a floating point value. or a schedule\n            that is a `tf.keras.optimizers.schedules.LearningRateSchedule`\n            The learning rate.\n          beta_1: A `float` value or a constant `float` tensor.\n            The exponential decay rate for the 1st moment estimates.\n          beta_2: A `float` value or a constant `float` tensor.\n            The exponential decay rate for the 2nd moment estimates.\n          epsilon: A small constant for numerical stability.\n            This epsilon is \"epsilon hat\" in\n            [Adam: A Method for Stochastic Optimization. Kingma et al., 2014]\n            (http://arxiv.org/abs/1412.6980) (in the formula just\n            before Section 2.1), not the epsilon in Algorithm 1 of the paper.\n          amsgrad: `boolean`. Whether to apply AMSGrad variant of this\n            algorithm from the paper \"On the Convergence of Adam and beyond\".\n            Note that this argument is currently not supported and the\n            argument can only be `False`.\n          name: Optional name for the operations created when applying\n            gradients. Defaults to \"LazyAdam\".\n          **kwargs: keyword arguments. Allowed to be {`clipnorm`, `clipvalue`,\n            `lr`, `decay`}. `clipnorm` is clip gradients by norm; `clipvalue`\n            is clip gradients by value, `decay` is included for backward\n            compatibility to allow time inverse decay of learning rate. `lr`\n            is included for backward compatibility, recommended to use\n            `learning_rate` instead.\n        \"\"\"\n        super().__init__(\n            learning_rate=learning_rate,\n            beta_1=beta_1,\n            beta_2=beta_2,\n            epsilon=epsilon,\n            amsgrad=amsgrad,\n            name=name,\n            **kwargs,\n        )\n\n    def _resource_apply_sparse(self, grad, var, indices):\n        var_dtype = var.dtype.base_dtype\n        lr_t = self._decayed_lr(var_dtype)\n        beta_1_t = self._get_hyper(\"beta_1\", var_dtype)\n        beta_2_t = self._get_hyper(\"beta_2\", var_dtype)\n        local_step = tf.cast(self.iterations + 1, var_dtype)\n        beta_1_power = tf.math.pow(beta_1_t, local_step)\n        beta_2_power = tf.math.pow(beta_2_t, local_step)\n        epsilon_t = tf.convert_to_tensor(self.epsilon, var_dtype)\n        lr = lr_t * tf.math.sqrt(1 - beta_2_power) / (1 - beta_1_power)\n\n        # \\\\(m := beta1 * m + (1 - beta1) * g_t\\\\)\n        m = self.get_slot(var, \"m\")\n        m_t_slice = beta_1_t * tf.gather(m, indices) + (1 - beta_1_t) * grad\n        m_update_op = self._resource_scatter_update(m, indices, m_t_slice)\n\n        # \\\\(v := beta2 * v + (1 - beta2) * (g_t * g_t)\\\\)\n        v = self.get_slot(var, \"v\")\n        v_t_slice = beta_2_t * tf.gather(v, indices) + (1 - beta_2_t) * tf.math.square(\n            grad\n        )\n        v_update_op = self._resource_scatter_update(v, indices, v_t_slice)\n\n        # \\\\(variable += -learning_rate * m_t / (epsilon_t + sqrt(v_t))\\\\)\n        var_slice = -lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)\n        var_update_op = self._resource_scatter_add(var, indices, var_slice)\n\n        return tf.group(*[var_update_op, m_update_op, v_update_op])\n", "path": "tensorflow_addons/optimizers/lazy_adam.py"}], "after_files": [{"content": "# Copyright 2019 The TensorFlow Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ==============================================================================\n\"\"\"Variant of the Adam optimizer that handles sparse updates more efficiently.\n\nCompared with the original Adam optimizer, the one in this file can\nprovide a large improvement in model training throughput for some\napplications. However, it provides slightly different semantics than the\noriginal Adam algorithm, and may lead to different empirical results.\n\"\"\"\n\nimport tensorflow as tf\nfrom tensorflow_addons.utils.types import FloatTensorLike\n\nfrom typeguard import typechecked\nfrom typing import Union, Callable\n\n\n@tf.keras.utils.register_keras_serializable(package=\"Addons\")\nclass LazyAdam(tf.keras.optimizers.Adam):\n    \"\"\"Variant of the Adam optimizer that handles sparse updates more\n    efficiently.\n\n    The original Adam algorithm maintains two moving-average accumulators for\n    each trainable variable; the accumulators are updated at every step.\n    This class provides lazier handling of gradient updates for sparse\n    variables.  It only updates moving-average accumulators for sparse variable\n    indices that appear in the current batch, rather than updating the\n    accumulators for all indices. Compared with the original Adam optimizer,\n    it can provide large improvements in model training throughput for some\n    applications. However, it provides slightly different semantics than the\n    original Adam algorithm, and may lead to different empirical results.\n\n    Note, amsgrad is currently not supported and the argument can only be\n    False.\n    \"\"\"\n\n    @typechecked\n    def __init__(\n        self,\n        learning_rate: Union[FloatTensorLike, Callable] = 0.001,\n        beta_1: FloatTensorLike = 0.9,\n        beta_2: FloatTensorLike = 0.999,\n        epsilon: FloatTensorLike = 1e-7,\n        amsgrad: bool = False,\n        name: str = \"LazyAdam\",\n        **kwargs,\n    ):\n        \"\"\"Constructs a new LazyAdam optimizer.\n\n        Args:\n          learning_rate: A `Tensor` or a floating point value. or a schedule\n            that is a `tf.keras.optimizers.schedules.LearningRateSchedule`\n            The learning rate.\n          beta_1: A `float` value or a constant `float` tensor.\n            The exponential decay rate for the 1st moment estimates.\n          beta_2: A `float` value or a constant `float` tensor.\n            The exponential decay rate for the 2nd moment estimates.\n          epsilon: A small constant for numerical stability.\n            This epsilon is \"epsilon hat\" in\n            [Adam: A Method for Stochastic Optimization. Kingma et al., 2014]\n            (http://arxiv.org/abs/1412.6980) (in the formula just\n            before Section 2.1), not the epsilon in Algorithm 1 of the paper.\n          amsgrad: `boolean`. Whether to apply AMSGrad variant of this\n            algorithm from the paper \"On the Convergence of Adam and beyond\".\n            Note that this argument is currently not supported and the\n            argument can only be `False`.\n          name: Optional name for the operations created when applying\n            gradients. Defaults to \"LazyAdam\".\n          **kwargs: keyword arguments. Allowed to be {`clipnorm`, `clipvalue`,\n            `lr`, `decay`}. `clipnorm` is clip gradients by norm; `clipvalue`\n            is clip gradients by value, `decay` is included for backward\n            compatibility to allow time inverse decay of learning rate. `lr`\n            is included for backward compatibility, recommended to use\n            `learning_rate` instead.\n        \"\"\"\n        super().__init__(\n            learning_rate=learning_rate,\n            beta_1=beta_1,\n            beta_2=beta_2,\n            epsilon=epsilon,\n            amsgrad=amsgrad,\n            name=name,\n            **kwargs,\n        )\n\n    def _resource_apply_sparse(self, grad, var, indices):\n        var_dtype = var.dtype.base_dtype\n        lr_t = self._decayed_lr(var_dtype)\n        beta_1_t = self._get_hyper(\"beta_1\", var_dtype)\n        beta_2_t = self._get_hyper(\"beta_2\", var_dtype)\n        local_step = tf.cast(self.iterations + 1, var_dtype)\n        beta_1_power = tf.math.pow(beta_1_t, local_step)\n        beta_2_power = tf.math.pow(beta_2_t, local_step)\n        epsilon_t = tf.convert_to_tensor(self.epsilon, var_dtype)\n        lr = lr_t * tf.math.sqrt(1 - beta_2_power) / (1 - beta_1_power)\n\n        # \\\\(m := beta1 * m + (1 - beta1) * g_t\\\\)\n        m = self.get_slot(var, \"m\")\n        m_t_slice = beta_1_t * tf.gather(m, indices) + (1 - beta_1_t) * grad\n        m_update_op = self._resource_scatter_update(m, indices, m_t_slice)\n\n        # \\\\(v := beta2 * v + (1 - beta2) * (g_t * g_t)\\\\)\n        v = self.get_slot(var, \"v\")\n        v_t_slice = beta_2_t * tf.gather(v, indices) + (1 - beta_2_t) * tf.math.square(\n            grad\n        )\n        v_update_op = self._resource_scatter_update(v, indices, v_t_slice)\n\n        # \\\\(variable += -learning_rate * m_t / (epsilon_t + sqrt(v_t))\\\\)\n        var_slice = lr * m_t_slice / (tf.math.sqrt(v_t_slice) + epsilon_t)\n        var_update_op = self._resource_scatter_sub(var, indices, var_slice)\n\n        return tf.group(*[var_update_op, m_update_op, v_update_op])\n\n    def _resource_scatter_update(self, resource, indices, update):\n        return self._resource_scatter_operate(\n            resource, indices, update, tf.raw_ops.ResourceScatterUpdate\n        )\n\n    def _resource_scatter_sub(self, resource, indices, update):\n        return self._resource_scatter_operate(\n            resource, indices, update, tf.raw_ops.ResourceScatterSub\n        )\n\n    def _resource_scatter_operate(self, resource, indices, update, resource_scatter_op):\n        resource_update_kwargs = {\n            \"resource\": resource.handle,\n            \"indices\": indices,\n            \"updates\": update,\n        }\n\n        return resource_scatter_op(**resource_update_kwargs)\n", "path": "tensorflow_addons/optimizers/lazy_adam.py"}]}