Store viewport display color and toggle shading type
That's not that easy as you might think and there are a few concepts involved.


For one, you would have to find a reliable way to store the actual object pointer or at least the name of the object and its corresponding viewport color for all selected objects. I would recommend register a CollectionProperty per scene and set its type to a prevously declared PropertyGroup to hold an object and its original color per item:
class CUSTOM_PG_objectColors(bpy.types.PropertyGroup):
    # name: bpy.props.StringProperty()
    obj_color: bpy.props.FloatVectorProperty(size=4)

bpy.types.Scene.custom_color_coll = bpy.props.CollectionProperty(
    name=&quot;Custom Object Collection&quot;,
    type=CUSTOM_PG_objectColors)

Even better would be using a PointerProperty for the actual objects, further reading:

Is it possible to use bpy.props.PointerProperty to store a pointer to an object?
Populate a list with custom property dictionary data
How can I store and retrieve a custom list in a blend file?

Next, in case your custom color is already assigned to Material.diffuse_color, you would have compare the color components due to limitations of floating point values before adding the object and its color to the list:
# Get the collection
obj_coll = context.scene.custom_color_coll

# Add the name of the object and its material to the list
for obj in context.selected_objects:
    mat = obj.active_material
    
    # Compare the colors per component before adding the item to the list
    self.color_match(mat.diffuse_color, self.color)
        item = obj_coll.add()
        item.name = obj.name
        item.obj_color = mat.diffuse_color
        # ... and set your custom color
        mat.diffuse_color = self.color

Further reading:

How to compare colour values in Blender using Python?
Code to toggle viewport display material alpha

And finally, notice that you do not need to iterate through the Screen.areas in order to set View3DShading.color_type since the operator is already part of the properties panel in 3D View. Consider adding a check if there is no material assigned to the object.
import bpy
from mathutils import Vector

class CUSTOM_PG_objectColors(bpy.types.PropertyGroup):
    # name: bpy.props.StringProperty()
    obj_color: bpy.props.FloatVectorProperty(size=4)
    
class CUSTOM_OT_displayColors(bpy.types.Operator):
    &quot;&quot;&quot;Tooltip&quot;&quot;&quot;
    bl_idname = &quot;view3d.custom_display_colors&quot;
    bl_label = &quot;Custom Display Colors&quot;
    
    action : bpy.props.EnumProperty(
        items=(
            ('SET', &quot;Set custom Display Colors&quot;, &quot;&quot;),
            ('RESET', &quot;Reset Display Colors&quot;, &quot;&quot;)))

    color : bpy.props.FloatVectorProperty(
        size=4, default=(1.0, 1.0, 0.0, 1.0))
        
    @classmethod
    def poll(cls, context):
        return len(context.selected_objects)

    def color_match(self, col1, col2, tol=0.001):
        def vector(col):
            # sanitize range (-2, 3, 5) = (0, 1, 1)
            return Vector([max(0, min(1, c)) for c in col])

        d = vector(col1) - vector(col2)
        return d.length &lt;= tol

    def execute(self, context):
        # Get a reference to the list composition
        obj_coll = context.scene.custom_color_coll
        
        if self.action == 'SET': 
            
            # Add the name of the object and its material to the list
            for obj in context.selected_objects:
                mat = obj.active_material
 
                if not self.color_match(mat.diffuse_color, self.color):
                    item = obj_coll.add()
                    item.name = obj.name
                    item.obj_color = mat.diffuse_color
                    # ... and set your custom color
                    mat.diffuse_color = self.color

            # Set Shading to 'TEXTURE'
            context.area.spaces.active.shading.color_type = 'TEXTURE'
            
        else:
            # Iterate through the custom list and reset the color
            for item in obj_coll:
                obj = context.scene.objects.get(item.name)
                if obj:
                    obj.active_material.diffuse_color = item.obj_color
            
            # Clear the list
            obj_coll.clear()
            
            # Set Shading to 'OBJECT'
            #context.area.spaces.active.shading.color_type = 'OBJECT'
        
        return {'FINISHED'}

class CUSTOM_PT_viewportToggles(bpy.types.Panel):          
    bl_label = &quot;Toggle viewport&quot;
    bl_space_type = &quot;VIEW_3D&quot;
    bl_region_type = &quot;UI&quot;
    bl_category = 'Toggle viewport'
    
    def draw (self, context):
        layout = self.layout
        
        layout.operator(
            CUSTOM_OT_displayColors.bl_idname, 
            text=&quot;Set custom Viewport Colors&quot;).action = 'SET'
        layout.operator(
            CUSTOM_OT_displayColors.bl_idname, 
            text=&quot;Reset Viewport Colors&quot;).action = 'RESET'
        
        layout.prop(context.scene, &quot;custom_display_bool&quot;)


def register():
    bpy.utils.register_class(CUSTOM_PG_objectColors)
    bpy.utils.register_class(CUSTOM_PT_viewportToggles)
    bpy.utils.register_class(CUSTOM_OT_displayColors)
    
    bpy.types.Scene.custom_color_coll = bpy.props.CollectionProperty(
        name=&quot;Custom Object Collection&quot;,
        type=CUSTOM_PG_objectColors)

def unregister():
    bpy.utils.unregister_class(CUSTOM_OT_displayColors)
    bpy.utils.unregister_class(CUSTOM_PT_viewportToggles)
    bpy.utils.unregister_class(CUSTOM_PG_objectColors)


if __name__ == &quot;__main__&quot;:
    register()


Also a toggle usually means a BoolProperty. As the name suggests it's typically used to store a simple state rather than assigning values to other properties like the viewport color. You can trick it using its update function though:
def update_func(scene, context):
    if scene.custom_display_bool:
        bpy.ops.view3d.custom_display_colors(action='SET')
    else:
        bpy.ops.view3d.custom_display_colors(action='RESET')
...

bpy.types.Scene.custom_display_bool = bpy.props.BoolProperty(
    name=&quot;Display Toggle&quot;, update=update_func)

Related:

How to pass multiple operator properties via UI layout?
How can I add a checkbox in the tools UI?