diff --git a/src/attr/validators.py b/src/attr/validators.py
--- a/src/attr/validators.py
+++ b/src/attr/validators.py
@@ -270,15 +270,16 @@ def optional(validator):
     which can be set to ``None`` in addition to satisfying the requirements of
     the sub-validator.
 
-    :param validator: A validator (or a list of validators) that is used for
-        non-``None`` values.
-    :type validator: callable or `list` of callables.
+    :param Callable | tuple[Callable] | list[Callable] validator: A validator
+        (or validators) that is used for non-``None`` values.
 
     .. versionadded:: 15.1.0
     .. versionchanged:: 17.1.0 *validator* can be a list of validators.
+    .. versionchanged:: 23.1.0 *validator* can also be a tuple of validators.
     """
-    if isinstance(validator, list):
+    if isinstance(validator, (list, tuple)):
         return _OptionalValidator(_AndValidator(validator))
+
     return _OptionalValidator(validator)
 
 

diff --git a/tests/test_validators.py b/tests/test_validators.py
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -384,7 +384,12 @@ def test_repr(self, ifoo):
 
 
 @pytest.mark.parametrize(
-    "validator", [instance_of(int), [always_pass, instance_of(int)]]
+    "validator",
+    [
+        instance_of(int),
+        [always_pass, instance_of(int)],
+        (always_pass, instance_of(int)),
+    ],
 )
 class TestOptional:
     """
@@ -437,6 +442,11 @@ def test_repr(self, validator):
                 "<optional validator for _AndValidator(_validators=[{func}, "
                 "<instance_of validator for type <class 'int'>>]) or None>"
             ).format(func=repr(always_pass))
+        elif isinstance(validator, tuple):
+            repr_s = (
+                "<optional validator for _AndValidator(_validators=({func}, "
+                "<instance_of validator for type <class 'int'>>)) or None>"
+            ).format(func=repr(always_pass))
         else:
             repr_s = (
                 "<optional validator for <instance_of validator for type "
diff --git a/tests/typing_example.py b/tests/typing_example.py
--- a/tests/typing_example.py
+++ b/tests/typing_example.py
@@ -236,6 +236,15 @@ class Validated:
     p: Any = attr.ib(
         validator=attr.validators.not_(attr.validators.in_("abc"), msg=None)
     )
+    q: Any = attr.ib(
+        validator=attrs.validators.optional(attrs.validators.instance_of(C))
+    )
+    r: Any = attr.ib(
+        validator=attrs.validators.optional([attrs.validators.instance_of(C)])
+    )
+    s: Any = attr.ib(
+        validator=attrs.validators.optional((attrs.validators.instance_of(C),))
+    )
 
 
 @attr.define

Optional validator should handle a tuple of validators
See relevant discussion in this discussion:
https://github.com/python-attrs/attrs/pull/925#discussion_r827665676
