General purpose input validation GUI
If the goal is "general purpose" I would be inclined to start from a much simpler premise, allowing users (i.e. developers) to build GUIs with the features that they need. Using object-oriented techniques you could subclass the tkinter widgets and extend them as needed. For example:

import tkinter as tk
from tkinter import messagebox


class ValidEntry(tk.Entry):

    def __init__(self, *args, validator=lambda text: True, **kwargs):
        super().__init__(*args, **kwargs)
        self.validator = validator

    def get(self):
        text = super().get()
        if not self.validator(text):
            raise ValueError('Invalid input')
        return text


This is now a reusable component; it can be dropped in wherever a regular tk.Entry is required (indeed the default validator allows it to be a direct replacement if validation isn't actually needed). The next step up is then:

class ValidatorFrame(tk.Frame):

    INSTRUCTION_FONT = '20px'

    def __init__(self, root, *args, button_text='Validate', instructions=None,
                 validator=lambda text: True, **kwargs):
        super().__init__(root, *args, **kwargs)
        if instructions is None:
            instructions = validator.__doc__
        self.instructions = tk.Label(
            root,
            font=INSTRUCTION_FONT,
            justify=tk.LEFT,
            text=instructions
        )
        self.instructions.pack(expand=1, fill=tk.X)
        self.user_input = ValidEntry(root, validator=validator)
        self.user_input.pack(expand=1, fill=tk.X)
        self.validate = tk.Button(root, command=self.validate, text=button_text)
        self.validate.pack()

    def validate(self):
        try:
            text = self.user_input.get()
        except ValueError:
            messagebox.showerror(
                "Input NOT valid.",
                "Please try again and enter a valid input."
            )
        else:
            messagebox.showinfo(
                "Input valid.",
                "Congratulations, you entered valid input."
            )


Again, this is a component that can be easily used elsewhere. One final step outward:

class TestGui(tk.Tk):

    TITLE_FONT = '25px'

    def __init__(self, *args, title=None, validator=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.title_label = tk.Label(self, font=self.TITLE_FONT, text=title)
        self.title_label.pack(expand=1, fill=tk.X)
        self.frame = ValidatorFrame(self, validator=validator)
        self.frame.pack(expand=1, fill=tk.X)
        if title is None:
            title = validator.__name__.replace('_', ' ').capitalize()
        self.wm_title(title)


By building up from basic components, you give yourself and your users a lot more flexibility. You can now launch this (using the validator you've already written) as simply as:

if __name__ == '__main__':
    app = TestGui(validator=is_valid_salutation)
    app.mainloop()


It's slightly more code, but a lot more flexible. One thing I haven't put much thought into is where the text would go once valid...



A few other things to note:


import tkinter as tk saves you repeating a few extra characters all over the place;
You tend to end up with a lot of keyword arguments to widgets, so I keep them in alphabetical order; and
Factoring out the styling information makes it easier to reuse, too.